﻿using System.Collections;
using Bingo.LocalDB.Entity;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using Object = UnityEngine.Object;

// using TMPro;

public class Bubble: MonoBehaviour
{
    public float fireForce = 2400f;
    public Rigidbody2D _rigidBody;
    private bool firstCollisionEntered;
    private Vector2 fireVector;
    public bool setOnStart;
    public int startNumber;
    public int number;
    public long id;

    private SpriteRenderer _renderer;

    public TextMeshPro numberTxt;

    public Text text;
    
    public GameObject bubbleImage;

    private float bubbleSize = 1;

    [HideInInspector]
    public BubbleState State;

    private float deadDuration;

    public bool collisionStatus = true;

    public Color[] bubbleColors;

    private Collider2D _innerCollider2D;

    public float _radius = 64;

    public BubbleStatus status = BubbleStatus.STOP;
    
    
    private void Awake()
    {
        this._innerCollider2D = this.gameObject.GetComponent<CircleCollider2D>();
        this._rigidBody = this.gameObject.GetComponent<Rigidbody2D>();
        this._renderer = this.GetComponent<SpriteRenderer>();
    }

    private void Start()
    {
    }

    private void Update()
    {
        this.readyColor = this.GetColor();
        // Debug.Log("---------------> this._rigidBody.velocity.sqrMagnitude : " +this._rigidBody.velocity.sqrMagnitude);
        if (this._rigidBody.velocity.sqrMagnitude > 1)
        {
            this.status = BubbleStatus.RUNNING;
        }
        else
        {
            this.status = BubbleStatus.STOP;
        }
    }

    public void Fire(Vector2 normalizedVector)
    {
        this.collisionStatus = true;
        this.fireVector = normalizedVector;
        this.bubbleImage.SetActive(false);
        this._rigidBody.velocity = normalizedVector * this.fireForce;
        this.firstCollisionEntered = false;
        this.State = BubbleState.Live;
        this.ResetScale();
        this.deadDuration = 0.0f;
        this._rigidBody.isKinematic = false;
        //TODO 发射数量
        /*int fireCount = DBHelper.Get<int>(DBKeys.FireCount);
        fireCount++;
        DBHelper.Save(DBKeys.FireCount, fireCount);*/
    }

    private void OnCollisionEnter2D(Collision2D col)
    {
        //this._rigidBody.velocity = this.fireVector * this.fireForce;
    }

    private void OnCollisionStay2D(Collision2D col)
    {
        if (col.gameObject.tag == "bubble")
        {
            Bubble bubble = col.gameObject.GetComponent<Bubble>();
            // Debug.Log("----------> this.State : " + this.State + ", bubble.State : " + bubble.State);
            if (this.State != BubbleState.Live || bubble.State != BubbleState.Live || this.number != bubble.number)
                return;
            
            float v1 = this.GetVelocity(this);
            float v2 = this.GetVelocity(bubble);
            if (v1 < v2)
            {
                this.Destroy();
                bubble.Merge();
                this.CreateBoomEff(this);
            }
            else
            {
                bubble.Destroy();
                this.Merge();
                this.CreateBoomEff(bubble);
            }
        }
    }

    /*
    private void OnTriggerStay2D(Collider2D other)
    {
        if (other.gameObject.tag == "gameover")
        {
            if (other.GetComponent<Bubble>().State != BubbleState.Live || this.State != BubbleState.Live)
                return;
            this.deadDuration += Time.deltaTime;
            if (this.deadDuration >= 3f)
            {
                Debug.Log("deadduration1:" + deadDuration);
                // 游戏结束
                if (GameController.Instance.GameStatus == GameStatus.RUNNING)
                {
                    Time.timeScale = 0f;
                    GameController.Instance.GameStatus = GameStatus.STOP;
                    Debug.Log("deadduration2:" + deadDuration + "  gamestatus:" + GameController.Instance.GameStatus);
                    //Shooter.shooter.GameOver();
                    GameOverEventArgs args = new GameOverEventArgs();
                    GameEntry.EventSystem.Fire(this, args);
                }
            }
        }
    }*/

    private void OnTriggerEnter2D(Collider2D col)
    {
        if (col.gameObject.tag.Equals("bubble"))
        {
            if (col.GetComponent<Bubble>().State != BubbleState.Live || this.State != BubbleState.Live)
                return;

            Bubble bubble = col.gameObject.GetComponent<Bubble>();
            BubbleCollisionAnim(col.gameObject);
            if (!this.firstCollisionEntered)
            {
                this.firstCollisionEntered = true;
                this._rigidBody.gravityScale = 0;
            }

            if (this.number == bubble.number)
            {
                float v1 = GetVelocity(this);
                float v2 = GetVelocity(bubble);
                if (v1 < v2)
                {
                    this.Destroy();
                    bubble.Merge();
                    CreateBoomEff(this);
                }
                else
                {
                    bubble.Destroy();
                    this.Merge();
                    CreateBoomEff(bubble);
                }

                //if (bubble.id > this.id)
                //{
                //    this.Destroy();
                //    bubble.Merge();
                //    CreateBoomEff(this);
                //}
                //else
                //{
                //    bubble.Destroy();
                //    this.Merge();
                //    CreateBoomEff(bubble);
                //}
            }
        }

        if (this.firstCollisionEntered || col.gameObject.tag.ToLower() != "pool")
            return;
        this.fireVector = new Vector2(this.fireVector.x * -1f, this.fireVector.y);
    }

    public int SetNumber(int _number, bool playSizeAnimation = true)
    {
        this.number = _number;
        this._renderer.sprite = BubbleSpawner.Instance.GetSpriteByNumber(_number);
        this.numberTxt.text = this.GetValue(this.number).ToString();
        this.text.text = this.GetValue(this.number).ToString();
        if (_number < 7)
        {
            this.text.fontSize = 65;
        }
        else if (_number >= 7 && _number < 10)
        {
            this.text.fontSize = 55;
        }
        else
        {
            this.text.fontSize = 45;
        }

        //this.text.color = BubbleSpawner.Instance.GetColor(_number - 1);

        if (!playSizeAnimation)
        {
            if (this.State == BubbleState.Live)
            {
                this.transform.localScale = Vector3.one * this.GetSize(this.number);
            }
        }
        else
        {
            this.StopCoroutine(nameof(this.PlayMergeAndScaleAnim));
            this.StartCoroutine(nameof(this.PlayMergeAndScaleAnim));
        }

        if (this.setOnStart)
        {
            this._rigidBody.isKinematic = false;
            this.bubbleImage.SetActive(false);
            //this._rigidBody.gravityScale = -50f;
            this.State = BubbleState.Live;
            this.firstCollisionEntered = true;
        }

        //NumberManager.Instance.SetMaxValueInGame(this.number);

        return GetValue(number);
    }

    public void BubbleCollisionAnim(GameObject go)
    {
        Animator anim = this.GetComponent<Animator>();
        anim.enabled = true;
        Bubble bubble = go.GetComponent<Bubble>();
        //Debug.Log("coll_bubble:" + bubble.collisionStatus);

        if (bubble.collisionStatus)
        {
            //Debug.Log("collisionStatus:" + collisionStatus);
            this.GetComponent<Animator>().Play("Anim_tanqiudonghua", 0, 0);
            go.GetComponent<Animator>().Play("Anim_tanqiudonghua", 0, 0);
        }

        StartCoroutine(SetBubbleCollisionStatus(bubble));
    }

    private IEnumerator SetBubbleCollisionStatus(Bubble bubble)
    {
        yield return new WaitForSeconds(0.1f);
        bubble.collisionStatus = false;
    }

    public void ResetScale()
    {
        this.transform.localScale = Vector3.one * this.GetSize(this.number);
    }

    private IEnumerator PlayMergeAndScaleAnim()
    {
        var nextSize = this.GetSize(this.number);
        var addSize = nextSize - this.transform.localScale.x;
        var animationFrameRate = 30f;
        var sizeForEachFrame = addSize / animationFrameRate;
        var animationFrameTime = 0.25f / animationFrameRate;

        while (animationFrameRate > 0.0)
        {
            yield return new WaitForSeconds(animationFrameTime);
            this.transform.localScale += Vector3.one * sizeForEachFrame;
            --animationFrameRate;
            //if (GameManager.Instance.readyBubble != null) 
            //GameManager.Instance.bubbleBg.transform.localScale = GameManager.Instance.readyBubble.transform.localScale;
        }

        this.State = BubbleState.Live;
    }

    private int GetValue(int _number)
    {
        return (int) Mathf.Pow(2f, _number);
    }

    private float GetSize(int _number)
    {
        float size = 0.55f;
        if (_number == 1)
        {
            return size;
        }

        for (int i = 1; i < _number; ++i)
        {
            if (i < 4)
                size += 0.05f;
            else
                size += 0.04f;
        }

        bubbleSize = size;
        return size;
    }

    public float BubbleSize()
    {
        return this.bubbleSize;
    }

    public float BubbleR()
    {
        return this.bubbleSize * 50;
    }

    public void Merge()
    {
        // Debug.Log("--------------------> merge ");
        this.State = BubbleState.Merging;
        GameManager.Instance.RemoveBubble(this.number, this.id);
        int score = this.SetNumber(this.number + 1, true);
        GameManager.Instance.SaveBubble(this);
        GameManager.Instance.IncreaseScore(score);
        GameManager.Instance.UpdateBestScore(score);

        //TODO 合并数量
        /*int mc = DBHelper.Get<int>(DBKeys.MergeCount, 0);
        mc++;
        DBHelper.Save(DBKeys.MergeCount, mc);*/
    }

    public void Destroy()
    {
        GameManager.Instance.RemoveBubble(this.number, this.id);
        this.State = BubbleState.Dead;
        this.StopCoroutine("PlayMergeAndScaleAnim");
        Object.Destroy(this.gameObject);
    }

    public void SetBubbleOrder(bool isBorn)
    {
        this._renderer.sortingOrder = isBorn? 20 : 10;
    }

    public void CreateBoomEff(Bubble bubble)
    {
        ParticleSystem boomPs = GameManager.Instance.boom;
        ParticleSystem.MainModule mm = boomPs.main;
        ParticleSystem.MainModule mm1 = boomPs.gameObject.transform.Find("posui_01").GetComponent<ParticleSystem>().main;
        mm.startColor = this.readyColor;
        mm1.startColor = this.readyColor;
        Instantiate<ParticleSystem>(boomPs, bubble.transform.position, Quaternion.identity, GameManager.Instance.boomParent);
        boomPs.Play();
    }

    private Color readyColor;

    public Color GetColor()
    {
        //Debug.Log("color[]:" + this.number % this.bubbleColors.Length);
        return this.bubbleColors[this.number % this.bubbleColors.Length];
    }

    public float GetVelocity(Bubble bubble)
    {
        Vector2 v = bubble.GetComponent<Rigidbody2D>().velocity;
        float value = Mathf.Sqrt(Mathf.Pow(v.x, 2) + Mathf.Pow(v.y, 2));
        return value;
    }

    public void SetBubbleLive()
    {
        this.State = BubbleState.Live;
        this._innerCollider2D.isTrigger = false;
        Color c = this._renderer.color;
        c.a = 1f;
        this._renderer.color = c;
    }

    public void SetBubbleVirtual()
    {
        this.State = BubbleState.Virtual;
        this._innerCollider2D.isTrigger = true;
        Color c = this._renderer.color;
        c.a = 0.5f;
        this._renderer.color = c;
    }

    public bool OverLap(Bubble other)
    {
        Vector2 v = other.transform.localPosition - this.transform.localPosition;
        float minDistance = this._radius * this.transform.localScale.x + this._radius * other.transform.localScale.x;
        float distance = Mathf.Sqrt(v.x * v.x + v.y * v.y);
        return distance <= minDistance; 
    }
    
}

public class BubbleData : BaseEntity
{
    
    public float X;

    public float Y;

    public int Number;
}

public enum BubbleStatus
{
    STOP,
    RUNNING
}